﻿using System;

namespace Quest.Core.Repository
{
    /// <summary>
    /// 工作单元基类接口
    /// </summary>
    public interface IUnitOfWork
    {
        bool IsCommitted { get; set; }

        int Commit();

        void Rollback();
    }

    /// <summary>
    /// 仓储上下文工作单元接口，使用这个的一般情况是多个仓储之间存在事务性的操作，用于标记聚合根的增删改状态
    /// </summary>
    public interface IUnitOfWorkRepositoryContext : IUnitOfWork, IDisposable
    {
        /// <summary>
        /// 将聚合根的状态标记为新建，但EF上下文此时并未提交
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="obj"></param>
        void RegisterNew<TEntity>(TEntity obj) where TEntity : AggregateRoot;

        /// <summary>
        /// 将聚合根的状态标记为修改，但EF上下文此时并未提交
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="obj"></param>
        void RegisterModified<TEntity>(TEntity obj) where TEntity : AggregateRoot;

        /// <summary>
        /// 将聚合根的状态标记为删除，但EF上下文此时并未提交
        /// </summary>
        /// <typeparam name="TEntity"></typeparam>
        /// <param name="obj"></param>
        void RegisterDeleted<TEntity>(TEntity obj) where TEntity : AggregateRoot;
    }

    /// <summary>
    /// 表示EF的工作单元接口，因为DbContext是EF的对象
    /// </summary>
    public interface IEFUnitOfWork : IUnitOfWorkRepositoryContext
    {
        //DbContext context { get; }
    }

    /// <summary>
    /// 工作单实现类
    /// </summary>
    //[Export(typeof(IEFUnitOfWork))]
    public class EFUnitOfWork : IEFUnitOfWork
    {
        #region 属性
        //通过工作单元向外暴露的EF上下文对象
        //public DbContext context { get { return EFContext; } }

        //[Import(typeof(DbContext))]
        //public DbContext EFContext { get; set; }
        #endregion

        #region 构造函数
        public EFUnitOfWork()
        {
            //注册MEF
            //Regisgter.regisgter().ComposeParts(this);
        }
        #endregion

        #region IUnitOfWorkRepositoryContext接口
        public void RegisterNew<TEntity>(TEntity obj) where TEntity : AggregateRoot
        {
            //var state = context.Entry(obj).State;
            //if (state == EntityState.Detached)
            //{
            //    context.Entry(obj).State = EntityState.Added;
            //}
            IsCommitted = false;
        }

        public void RegisterModified<TEntity>(TEntity obj) where TEntity : AggregateRoot
        {
            //if (context.Entry(obj).State == EntityState.Detached)
            //{
            //    context.Set<TEntity>().Attach(obj);
            //}
            //context.Entry(obj).State = EntityState.Modified;
            IsCommitted = false;
        }

        public void RegisterDeleted<TEntity>(TEntity obj) where TEntity : AggregateRoot
        {
            //context.Entry(obj).State = EntityState.Deleted;
            IsCommitted = false;
        }
        #endregion

        #region IUnitOfWork接口

        public bool IsCommitted { get; set; }

        public int Commit()
        {
            if (IsCommitted)
            {
                return 0;
            }
            //try
            //{
            //    int result = context.SaveChanges();
            //    IsCommitted = true;
            //    return result;
            //}
            //catch (DbUpdateException e)
            //{
            //    throw e;
            //}
            throw new NotImplementedException();
        }

        public void Rollback()
        {
            IsCommitted = false;
        }
        #endregion

        #region IDisposable接口
        public void Dispose()
        {
            if (!IsCommitted)
            {
                //Commit();
            }
            //context.Dispose();
        }
        #endregion
    }
}
